package org.example.unsafe;

import org.example.optimistic.lock.ATM.Account;
import sun.misc.Unsafe;

/**
 * @author zhengdp
 * @Description 使用 Unsafe 实现 原子整数类
 * @Date 2022/11/27 20:25
 * @Created by zhengdp
 */
public class UnsafeAtomicInteger implements Account {

    public static void main(String[] args) {
        Account.demo(new UnsafeAtomicInteger(10000));
    }

    static final Unsafe UNSAFE;
    private volatile int value;
    private static final long valueOffset;
    static {
        UNSAFE = UnsafeAccessor.getUnsafe();
        try {
            valueOffset = UNSAFE.objectFieldOffset(UnsafeAtomicInteger.class.getDeclaredField("value"));
        } catch (NoSuchFieldException e) {
            // 静态代码块 没办法抛出异常（异常是检查异常，只能抛出运行时异常）
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public UnsafeAtomicInteger(int value) {
        this.value = value;
    }

    public int getValue(){
        return value;
    }

    public void decrement(int amount) {
        while(true) {
            int prev = this.value;
            int next = prev - amount;
            if(UNSAFE.compareAndSwapInt(this,valueOffset,prev,next)) {
                break;
            }
        }
    }


    @Override
    public Integer getBalance() {
        return getValue();
    }

    @Override
    public void withdraw(Integer amount) {
        decrement(amount);
    }
}
